package com.example.mytestdemo.text

import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.animation.addListener
import com.example.mytestdemo.extensions.safePostDelayed
import com.example.mytestdemo.utils.dp
import java.text.DecimalFormat
import kotlin.random.Random

/**
 * Created by QiuBin on 2021/8/25.
 * Describe: 上下滑动动画
 */
class UgcRollTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) {

    private var linearLayoutList = mutableListOf<LinearLayout>()
    private var textViewHeight: Int = 63 //单个数字的高度，也就是移动距离 99
    private var textViewWidth: Int = 0
    private var mPaint = Paint()
    private var textSize = 28
    private var textColor = Color.parseColor("#040A23")
    private var animatorSet = AnimatorSet()
    private var oldText: String? = null
    private var newText: String? = null//动画数据 = 真实数据 - 20
    private var realNumbers: Long = 0 //真实数据
    private var lastAnimationPosition = mutableListOf<Float>()
    private var newAnimationPosition = mutableListOf<Float>() //最终的动画位置
    private var textHeight: Int = 0
    private val decimalFormat = DecimalFormat("#,##0")
    private var isDelay = false //是否在等待动画的执行间隔

    init {
        orientation = HORIZONTAL
        mPaint.textSize = textSize.toFloat()
        val rect = Rect()
        mPaint.getTextBounds("9", 0, 1, rect)
        textHeight = rect.height().dp + 3.dp
        textViewWidth = rect.width().dp + 1.dp
    }

    fun setText(identifyNum: Long) {
        val text = decimalFormat.format(identifyNum)
        text ?: return
        if (identifyNum == realNumbers) return

        realNumbers = identifyNum
        if (newText == null) {
            //第一次更新，需要步进
            newText = decimalFormat.format(identifyNum - 20)
        } else {
            newText = decimalFormat.format(identifyNum) //一步到位，不要步进
        }

        initView()
        //先修正数据
        correctionData()
    }

    private fun initView() {
        if (oldText.isNullOrBlank()) {
            if (childCount > 0) {
                removeAllViews()
            }
            val stringBuilder = StringBuilder()
            for (i in 0 until (newText?.length ?: 0)) {
                val scrollView = NoScrollView(context)
                scrollView.isVerticalScrollBarEnabled = false
                val linearLayout = if (newText?.getOrNull(i) == ',') {
                    stringBuilder.append(",")
                    getLinearLayout(true)
                } else {
                    stringBuilder.append("0")
                    getLinearLayout()
                }
                linearLayoutList.add(linearLayout)
                scrollView.addView(linearLayout)
                addView(scrollView)
                lastAnimationPosition.add(i, 0f)
            }
            oldText = stringBuilder.toString()
        } else {
            val newTextLength = newText?.length ?: 0
            val oldTextLength = oldText?.length ?: 0
            val tempSize = newTextLength - oldTextLength
            //数据位数变大后，添加新增加位
            if (tempSize > 0) {
                for (z in tempSize - 1 downTo 0) {
                    val scrollView = NoScrollView(context)
                    scrollView.isVerticalScrollBarEnabled = false
                    val linearLayout = if (newText?.getOrNull(z) == ',') {
                        getLinearLayout(true)
                    } else {
                        getLinearLayout()
                    }
                    linearLayoutList.add(0, linearLayout)
                    scrollView.addView(linearLayout)
                    addView(scrollView, 0)
                    lastAnimationPosition.add(0, 0f)
                }
            }
            oldText = newText
        }
    }

    fun startAnimation() {
        post {
            textViewHeight = linearLayoutList[0].height / 11
            Log.d("@@HH", "textViewHeight $textViewHeight")
            startAnimation(false)
        }
    }

    private fun startAnimation(isFromStep: Boolean) {
        initView() //处理需不需要补零
        //先修正数据
        correctionData()
        computeLayout() //计算单个数字的滚动距离
        animatorSet.cancel()
        initAnimation(isFromStep)
        animatorSet.start()
        lastAnimationPosition.clear()
        lastAnimationPosition.addAll(newAnimationPosition)
    }

    private fun computeLayout() {
        newAnimationPosition.clear()
        newText?.indices?.forEach { position ->
            if (newText?.getOrNull(position) == ',') {
                newAnimationPosition.add(position, 0f)
            } else {
                newText?.getOrNull(position)?.let { char ->
                    val newPosition = char - '0'
                    if (newPosition == 0 && lastAnimationPosition.getOrNull(position) == -9f * textViewHeight) {
                        //如果当前是在9的位置， 需要动画到后面的那个0的位置
                        newAnimationPosition.add(position, -10 * textViewHeight.toFloat())
                    } else {
                        newAnimationPosition.add(position, -newPosition * textViewHeight.toFloat())
                    }
                }
            }
        }

    }

    /**
     * @param isFromStep 是否来之循环步进20
     */
    private fun initAnimation(isFromStep: Boolean) {
        Log.d("@@HH", "the size of textViewList is ${linearLayoutList.size}")
        Log.d("@@HH-", "lastAnimationPosition $lastAnimationPosition")
        Log.d("@@HH-", "newAnimationPosition $newAnimationPosition")
        var fixDigit = 0
        for ((index, linearLayout) in linearLayoutList.withIndex()) {
            //Log.d("@@HH", "index: $index, textView height: ${linearLayout.height}")
            val objectAnimation =
                ObjectAnimator.ofFloat(
                        linearLayout,
                        "translationY",
                        lastAnimationPosition.getOrNull(index) ?: 0f,
                        newAnimationPosition.getOrNull(index) ?: 0f
                )
            animatorSet.playTogether(objectAnimation)

            if (linearLayout.childCount == 1) {
                //逗号
                objectAnimation.duration = 0
            } else {
                if (fixDigit < 2) {
                    //前面两位不动，不包含 逗号
                    objectAnimation.duration = 0
                } else {
                    objectAnimation.duration = 500
                }
                fixDigit++
            }

        }

        animatorSet.removeAllListeners()
        animatorSet.addListener(onEnd = {
            isDelay = true
            //0.5s - 5s随机时间间隔
            safePostDelayed(currentRandomNumber()) {
                //开始进20
                startStep()
                isDelay = false
            }
        })
    }

    private fun currentRandomNumber(): Long {
        // 生成介于 0.5s 到 5s 之间的随机小数 动画时间0.5秒
        return Random.nextLong(500, 5000)
    }

    private fun startStep() {
        val currentValue = newText?.replace(",", "")?.toLongOrNull()
        currentValue ?: return
        if (realNumbers != currentValue) {
            //继续步进 20
            newText = decimalFormat.format(currentValue + 1)
            startAnimation(true)
        }
    }

    private fun correctionData() {
        lastAnimationPosition.forEachIndexed { index, fl ->
            if (fl == -10f * textViewHeight) {
                //当前显示在后面的那个0, 需要归位
                lastAnimationPosition[index] = 0f
                linearLayoutList.getOrNull(index)?.translationY = 0f
            }
        }
    }

    private fun getLinearLayout(isPoint: Boolean = false): LinearLayout {
        val linearLayout = LinearLayout(context)
        linearLayout.layoutParams =
            LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        linearLayout.orientation = VERTICAL
        if (isPoint) {
            linearLayout.addView(getTextView(","))
        } else {
            linearLayout.addView(getTextView("0"))
            linearLayout.addView(getTextView("1"))
            linearLayout.addView(getTextView("2"))
            linearLayout.addView(getTextView("3"))
            linearLayout.addView(getTextView("4"))
            linearLayout.addView(getTextView("5"))
            linearLayout.addView(getTextView("6"))
            linearLayout.addView(getTextView("7"))
            linearLayout.addView(getTextView("8"))
            linearLayout.addView(getTextView("9"))
            linearLayout.addView(getTextView("0")) //需要归位，所以循环多补个0
        }
        return linearLayout
    }

    @SuppressLint("SetTextI18n")
    private fun getTextView(num: String): TextView {
        val textView = TextView(context)
        if (num == ",") {
            textView.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        } else {
            textView.layoutParams = LayoutParams(textViewWidth, LayoutParams.WRAP_CONTENT)
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            textView.letterSpacing = 0f
        }
        textView.gravity = Gravity.CENTER
        textView.includeFontPadding = false
        textView.setLineSpacing(0f, 0f)
        textView.setTextColor(textColor)
        textView.text = num
        textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize.toFloat())
        textView.typeface = Typeface.defaultFromStyle(Typeface.BOLD);
        return textView
    }

    fun isRunning(): Boolean {
        return animatorSet.isRunning || isDelay
    }

    fun onDestroy() {
        animatorSet.cancel()
        animatorSet.removeAllListeners()
    }

}